<template>
<datetime-frame :visible="visible" @click="onHide" :double="true" ref="edtframe">
        <template v-slot:default="sps">
        <date-wrapper :isMobile="sps.isMobile" ref="dtpanels" @swipeleft="onSwipeleft" @swiperight="onSwiperight">
        <base-datetime
            :theme="sps.theme"
            :weekText="sps.weekText"
            :importants="sps.importants"
            :langs="sps.langs"
            

            :mode="mode"
            :umode="umode"
            :value="start"
            :min="minDo"
            :max="smax"
            @back="onModeShift(pMode)"
            @pick="onStartPick"
            @mode-shift="onModeShift"/>
        <base-datetime
            :theme="sps.theme"
            :weekText="sps.weekText"
            :importants="sps.importants"
            :langs="sps.langs"

            :showBackTime="false"
            :mode="mode"
            :umode="umode"
            :value="end"
            :min="emin"
            :max="maxDo"
            @pick="onEndPick"
            @mode-shift="onModeShift"/>
        </date-wrapper>
        </template>
        <template v-slot:footer="fps">
            <footer-bar 
                @time-navigate="onModeShift(Mode.time)"
                @done="onDone"
                @clear="onClear"
                :clear="fps.clear"
                :langs="fps.langs" 
                :theme="fps.theme" 
                :isMobile="fps.isMobile"

                :vDo="sDo"
                :sDo="sDo"
                :eDo="eDo"
                :min="minDo"
                :max="maxDo"
                :format="format"
                :umode="umode" 
                :mode="mode"
                />
        </template>
    </datetime-frame>
</template>
<script lang="ts">
import { computed, defineComponent, watch, ref } from 'vue'
import Evt from 'ph-evt'
import { PhDatepickerOpt } from './index.type'
import { destructDate, parseDate } from '../../shared/datetime'
import { Format, Mode } from './config'
import DatetimeFrame from './datetime-frame.vue'
import BaseDatetime from './date-time.vue'
import FooterBar from './dfooter.vue'
import DateWrapper from './date-wrapper.vue'
export default defineComponent({
    components:{
        DatetimeFrame,
        BaseDatetime,
        FooterBar,
        DateWrapper
    },
    setup() {
        const evt = new Evt()

        const edtframe = ref<InstanceType<typeof DatetimeFrame>>()
        const dtpanels = ref<InstanceType<typeof DateWrapper>>()
        const ename = "pick"
        const visible = ref(false)
        const currentPanel = ref(0)

        const start = ref<Date>(new Date())
        const end = ref<Date>(new Date())
        let pMode = Mode.date
        const mode = ref(Mode.date)
        const umode = ref(Mode.datetime)
        const format = ref(Format.datetime)
        const max = ref<string>()
        const min = ref<string>()
        
        const minDo = computed(()=>{
            return min.value?destructDate(parseDate(min.value,format.value)):false
        })
        const maxDo = computed(()=>{
            return max.value?destructDate(parseDate(max.value,format.value)):false
        })

        const sDo = computed(()=>{
            return destructDate(start.value)
        })
        const eDo = computed(()=>{
            return destructDate(end.value)
        })
        watch(()=>mode.value,(v:number)=>{
            if(v!==Mode.time)pMode = v
        })
        const setupUMode = (type:string)=>{
            switch(type){
                case "datetime":
                    umode.value = Mode.datetime
                    mode.value = Mode.date
                    break
                case "date":
                    mode.value = umode.value = Mode.date
                    break;
                case "year":
                    mode.value = umode.value = Mode.year
                    break
                case "month":
                    mode.value = umode.value = Mode.month
                    break
                case "time":
                    mode.value = umode.value = Mode.time
                    break
                default:
                    umode.value = Mode.datetime
                    mode.value = Mode.date
            }
        }
        const notify = (v:Record<string,number>|unknown)=>{
            evt.emit(ename,v)
            onHide()
        }
        const onModeShift = (m:number)=>{
            pMode = mode.value
            mode.value = m
        }
        const onHide = ()=>{
            visible.value = false
            edtframe.value?.restore()
            evt.off(ename)
        }
        const smax = computed(()=>{
            const maxDo = max.value?parseDate(max.value,format.value):false
            if(maxDo&&end.value){
                return destructDate(maxDo.getTime()>end.value.getTime()?end.value:maxDo)
            }
            if(maxDo)
                return destructDate(maxDo)
            if(end.value)
                return destructDate(end.value)
            return false
        })
        const emin = computed(()=>{
            const minDo = min.value?parseDate(min.value,format.value):false
            if(minDo&&start.value){
                return destructDate(minDo.getTime()>start.value.getTime()?minDo:start.value)
            }
            if(minDo)
                return destructDate(minDo)
            if(start.value)
                return destructDate(start.value)
            return false
        })
        const setInitDate = (s?:string,e?:string)=>{
            let sd = new Date(),
                ed = new Date();
            switch(umode.value){
                case Mode.time:{
                    if(!s&&!e){
                        const {yyyy,MM,dd} = destructDate(new Date())
                        start.value = new Date(yyyy,MM,dd,0,0,0)
                        end.value = new Date(yyyy,MM,dd,23,59,59)
                    }else if(!e){
                        start.value = parseDate(s as string,format.value)
                        const {yyyy,MM,dd} = destructDate(start.value)
                        end.value = new Date(yyyy,MM,dd,23,59,59)
                    }else if(!s){
                        end.value = parseDate(e as string,format.value)
                        const {yyyy,MM,dd} = destructDate(end.value)
                        start.value = new Date(yyyy,MM,dd,0,0,0)
                    }else{
                        start.value = parseDate(s as string,format.value)
                        end.value = parseDate(e as string,format.value)
                    }
                    break
                }
                default:{
                    if(!s&&!e){
                        start.value = sd
                        ed.setMonth(sd.getMonth()+1)
                        end.value = ed
                    }else if(!e){
                        start.value = parseDate(s as string,format.value)
                        ed = new Date(start.value.getTime())
                        ed.setMonth(start.value.getMonth()+1)
                        end.value = ed
                    }else if(!s){
                        end.value = parseDate(e as string,format.value)
                        sd = new Date(end.value.getTime())
                        sd.setMonth(end.value.getMonth()-1)
                        start.value = sd
                    }else{
                        start.value = parseDate(s as string,format.value)
                        end.value = parseDate(e as string,format.value)
                    }
                }
            }
        }
        const show = (s:string,e:string,opt:PhDatepickerOpt)=>{
            console.log(s,opt)
            evt.off(ename)
            edtframe.value?.save(opt)
            setupUMode(opt.mode)
            visible.value = true
            format.value = opt.format||Format[umode.value]

            max.value = opt.max
            min.value = opt.min

            start.value = s?parseDate(s,format.value):new Date()
            
            setInitDate(s,e)
            return {
                done(fn:()=>void){
                    evt.off(ename)
                    evt.once(ename,fn)
                }
            }
        }
        const getResult = (v:any,umode:number)=>{
            if(!v)return undefined
            const {yyyy,MM,dd,hh,mm,ss} = destructDate(v) 
            switch(umode){
                case Mode.datetime:
                    return {yyyy,MM,dd,hh,mm,ss}
                case Mode.date:
                    return {yyyy,MM,dd}
                case Mode.month:
                    return {yyyy,MM}
                case Mode.year:
                    return {yyyy}
                case Mode.time:
                    return {hh,mm,ss}
            }
        }
        const onDone = ()=>{
            const 
                sd = getResult(start.value,umode.value),
                ed = getResult(end.value,umode.value);
            notify([sd,ed])
        }
        const onClear = ()=>{
            notify(undefined)
        }
        const onStartPick = (v?:Date)=>{
            if(v)
            start.value = v
        }
        const onEndPick = (v?:Date)=>{
            if(v)
            end.value = v
        }

        const onSwipeleft = ()=>{
            if(!edtframe.value?.isMobile)return
            if(currentPanel.value===0)currentPanel.value=1
        }
        const onSwiperight = ()=>{
            if(!edtframe.value?.isMobile)return
            if(currentPanel.value===1)currentPanel.value=0
        }

        watch(()=>currentPanel.value,(n,o)=>{
            const [l,r] = dtpanels.value?.$el.querySelectorAll('.ph-datetime-panel')
            const footer = edtframe.value?.$el.querySelector('.ph-dt-mfooter')
            const tx = n===1?-100:0
            const transform = `translateX(${tx}%)`
            if(l)l.style.transform = transform
            if(r)r.style.transform = transform
            if(footer)footer.style.transform = `translateX(${tx/2}%)`
        })
        return {
            Mode,
            edtframe,
            dtpanels,
            show,
            minDo,
            maxDo,
            sDo,
            eDo,
            start,
            end,
            smax,
            emin,
            pMode,
            mode,
            umode,
            format,
            visible,
            onHide,
            onDone,
            onClear,
            onStartPick,
            onEndPick,
            onModeShift,
            onSwipeleft,
            onSwiperight
        }
    }
})
</script>